package com.jjsj.mall.service;

import com.google.gson.Gson;
import com.jjsj.mall.config.SwiftpassConfig;
import com.jjsj.mall.entity.OrderInfo;
import com.jjsj.mall.util.SignUtil;
import com.jjsj.mall.util.SignUtils;
import com.jjsj.mall.util.XmlUtils;
import com.jjsj.weixin.entity.WxUser;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

@SuppressWarnings("unchecked")
public class SwiftPayService {
    private static Logger log = LoggerFactory.getLogger(SwiftPayService.class);
    private final static String version = "2.0";
    private final static String charset = "UTF-8";
    //private final static String sign_type = "MD5";

    /**
     * <一句话功能简述>
     * <功能详细描述>支付请求
     *
     * @throws ServletException
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    public Map<String, String> pay(WxUser wxUser, OrderInfo orderInfo, String appId, String ip) throws IOException {
        log.debug("支付请求...");
//        SortedMap<String, String> map = XmlUtils.getParameterMap(req);
        SortedMap<String, String> map = new TreeMap();
        map.put("service", "pay.weixin.jspay");
        map.put("version", version);
        map.put("charset", charset);

        map.put("is_raw", "1");
        map.put("is_minipg", "1");
        map.put("mch_id", SwiftpassConfig.mch_id);
        map.put("body", orderInfo.getName());
        map.put("attach", orderInfo.getUserMessage());
        map.put("mch_create_ip", ip);
        map.put("sub_openid", wxUser.getOpenId());
        map.put("out_trade_no", orderInfo.getOrderNo());
        BigDecimal bigDecimal = orderInfo.getPaymentPrice();
        bigDecimal = bigDecimal.multiply(new BigDecimal("100"));
        BigInteger total_fee = bigDecimal.toBigInteger();
        map.put("total_fee", "" + total_fee.toString());
        map.put("sub_appid", appId);
        map.put("sign_type", "RSA_1_256");

        map.put("notify_url", SwiftpassConfig.notify_url);
        map.put("nonce_str", String.valueOf(new Date().getTime()));

        Map<String, String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        String sign_type = map.get("sign_type");

        map.put("sign", SignUtil.getSign(sign_type, preStr));

        String reqUrl = SwiftpassConfig.req_url;
        log.debug("reqUrl：" + reqUrl);
        System.out.println("请求xml：" + XmlUtils.toXml(map));
        log.debug("reqParams:" + XmlUtils.parseXML(map));
        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        Map<String, String> resultMap = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
            httpPost.setEntity(entityParams);
            httpPost.setHeader("Content-Type", "text/xml;utf-8");
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if (response != null && response.getEntity() != null) {
                resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                String reSign = resultMap.get("sign");
                sign_type = resultMap.get("sign_type");
                res = XmlUtils.toXml(resultMap);
                System.out.println("签名方式" + sign_type);
                log.debug("请求结果：" + res);
                System.out.println("请求结果：" + res);
                if (resultMap.containsKey("sign") && !SignUtil.verifySign(reSign, sign_type, resultMap)) {
                    res = "验证签名不通过";
                } else {
                    if ("0".equals(resultMap.get("status")) && "0".equals(resultMap.get("result_code"))) {
                        String pay_info = resultMap.get("pay_info");
                        log.debug("pay_info : " + pay_info);
                        res = "ok";
                    }
                }
            } else {
                res = "操作失败";
            }
        } catch (Exception e) {
            log.error("操作失败，原因：", e);
            res = "系统异常";
        } finally {
            if (response != null) {
                response.close();
            }
            if (client != null) {
                client.close();
            }
        }
        Map<String, String> result = new HashMap<String, String>();
        if ("ok".equals(res)) {
            result = resultMap;
        } else {
            result.put("status", "500");
            result.put("msg", res);
        }
        return resultMap;
    }

    /**
     * <一句话功能简述>
     * <功能详细描述>订单查询
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    public void query(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("订单查询...");
        SortedMap<String, String> map = XmlUtils.getParameterMap(req);

        map.put("service", "unified.trade.query");
        map.put("version", version);
        map.put("charset", charset);
        //map.put("sign_type", sign_type);
        map.put("mch_id", SwiftpassConfig.mch_id);

        String key = SwiftpassConfig.key;
        String reqUrl = SwiftpassConfig.req_url;
        map.put("nonce_str", String.valueOf(new Date().getTime()));

        Map<String, String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        String sign_type = map.get("sign_type");

        map.put("sign", SignUtil.getSign(sign_type, preStr));

        log.debug("reqUrl:" + reqUrl);

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
            httpPost.setEntity(entityParams);
            httpPost.setHeader("Content-Type", "text/xml;utf-8");
            client = HttpClients.createDefault();
            response = client.execute(httpPost);

            if (response != null && response.getEntity() != null) {
                Map<String, String> resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                String reSign = resultMap.get("sign");
                sign_type = resultMap.get("sign_type");
                res = XmlUtils.toXml(resultMap);
                System.out.println("签名方式" + sign_type);
                log.debug("请求结果：" + res);
                System.out.println("请求结果：" + res);
                if (resultMap.containsKey("sign") && !SignUtil.verifySign(reSign, sign_type, resultMap)) {
                    res = "验证签名不通过";
                } else {
                    if ("0".equals(resultMap.get("status"))) {
                        if ("0".equals(resultMap.get("result_code"))) {
                            log.debug("业务成功，在这里做相应的逻辑处理");
                            String trade_state = resultMap.get("trade_state");
                            log.debug("trade_state : " + trade_state);
                            log.debug("这里商户需要同步自己的订单状态。。。");
                        } else {
                            log.debug("业务失败，尝试重新请求，并查看错误代码描叙");
                        }
                    } else {
                        log.debug("这里是请求参数有问题...");
                    }
                }
            } else {
                res = "操作失败!";
            }
        } catch (Exception e) {
            log.error("操作失败，原因：", e);
            res = "操作失败";
        } finally {
            if (response != null) {
                response.close();
            }
            if (client != null) {
                client.close();
            }
        }
        Map<String, String> result = new HashMap<String, String>();
        if (res.startsWith("<")) {
            result.put("status", "200");
            result.put("msg", "操作成功，请在日志文件中查看");
        } else {
            result.put("status", "500");
            result.put("msg", res);
        }
        resp.getWriter().write(new Gson().toJson(result));
    }

    /**
     * <一句话功能简述>
     * <功能详细描述>退款查询
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    public void refundQuery(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("退款查询...");
        SortedMap<String, String> map = XmlUtils.getParameterMap(req);

        map.put("service", "unified.trade.refundquery");
        map.put("version", version);
        map.put("charset", charset);
        //map.put("sign_type", sign_type);

        String key = SwiftpassConfig.key;
        String reqUrl = SwiftpassConfig.req_url;
        map.put("mch_id", SwiftpassConfig.mch_id);
        map.put("nonce_str", String.valueOf(new Date().getTime()));

        Map<String, String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        String sign_type = map.get("sign_type");

        map.put("sign", SignUtil.getSign(sign_type, preStr));

        log.debug("reqUrl:" + reqUrl);

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
            httpPost.setEntity(entityParams);
            httpPost.setHeader("Content-Type", "text/xml;utf-8");
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if (response != null && response.getEntity() != null) {
                Map<String, String> resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                String reSign = resultMap.get("sign");
                sign_type = resultMap.get("sign_type");
                res = XmlUtils.toXml(resultMap);
                System.out.println("签名方式" + sign_type);
                log.debug("请求结果：" + res);
                System.out.println("请求结果：" + res);
                if (resultMap.containsKey("sign") && !SignUtil.verifySign(reSign, sign_type, resultMap)) {
                    res = "验证签名不通过";
                }
            } else {
                res = "操作失败!";
            }
        } catch (Exception e) {
            log.error("操作失败，原因：", e);
            res = "操作失败";
        } finally {
            if (response != null) {
                response.close();
            }
            if (client != null) {
                client.close();
            }
        }
        Map<String, String> result = new HashMap<String, String>();
        if (res.startsWith("<")) {
            result.put("status", "200");
            result.put("msg", "操作成功，请在日志文件中查看");
        } else {
            result.put("status", "500");
            result.put("msg", res);
        }
        resp.getWriter().write(new Gson().toJson(result));
    }

    /**
     * <一句话功能简述>
     * <功能详细描述>退款
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     * @see [类、类#方法、类#成员]
     */
    public void refund(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        log.debug("退款...");
        SortedMap<String, String> map = XmlUtils.getParameterMap(req);

        map.put("service", "unified.trade.refund");
        map.put("version", version);
        map.put("charset", charset);
        //map.put("sign_type", sign_type);

        String key = SwiftpassConfig.key;
        String reqUrl = SwiftpassConfig.req_url;
        map.put("mch_id", SwiftpassConfig.mch_id);
        map.put("op_user_id", SwiftpassConfig.mch_id);
        map.put("nonce_str", String.valueOf(new Date().getTime()));

        Map<String, String> params = SignUtils.paraFilter(map);
        StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
        SignUtils.buildPayParams(buf, params, false);
        String preStr = buf.toString();
        String sign_type = map.get("sign_type");

        map.put("sign", SignUtil.getSign(sign_type, preStr));

        log.debug("reqUrl:" + reqUrl);

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity entityParams = new StringEntity(XmlUtils.parseXML(map), "utf-8");
            httpPost.setEntity(entityParams);
            httpPost.setHeader("Content-Type", "text/xml;utf-8");
            client = HttpClients.createDefault();
            response = client.execute(httpPost);
            if (response != null && response.getEntity() != null) {
                Map<String, String> resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
                String reSign = resultMap.get("sign");
                sign_type = resultMap.get("sign_type");
                res = XmlUtils.toXml(resultMap);
                System.out.println("签名方式" + sign_type);
                log.debug("请求结果：" + res);
                System.out.println("请求结果：" + res);
                if (resultMap.containsKey("sign") && !SignUtil.verifySign(reSign, sign_type, resultMap)) {
                    res = "验证签名不通过";
                }
            } else {
                res = "操作失败!";
            }
        } catch (Exception e) {
            log.error("操作失败，原因：", e);
            res = "操作失败";
        } finally {
            if (response != null) {
                response.close();
            }
            if (client != null) {
                client.close();
            }
        }
        Map<String, String> result = new HashMap<String, String>();
        if (res.startsWith("<")) {
            result.put("status", "200");
            result.put("msg", "操作成功，请在日志文件中查看");
        } else {
            result.put("status", "500");
            result.put("msg", res);
        }
        resp.getWriter().write(new Gson().toJson(result));
    }
}
